package com.demarc.pesquisas.infraestrutura.persistencia;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import com.demarc.pesquisas.infraestrutura.mensagem.Mensagem;

public class ObjetoValidavel implements Serializable {

	public List<Mensagem> validar() {
		return validar(this);
	}

	private <E> List<Mensagem> validar(E obj) {
		List<Mensagem> mensagens = new ArrayList<Mensagem>();
		List<Mensagem> mensagensObrigatoriedade = new ArrayList<Mensagem>();
		List<String> parametros = null;

		ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
		Validator validator = factory.getValidator();
		Set<ConstraintViolation<E>> constraintViolations = validator
				.validate(obj);
		for (ConstraintViolation<E> violacao : constraintViolations) {
			String chaveMensagem = violacao.getConstraintDescriptor()
					.getAnnotation().annotationType().getName();

			String nomePropriedade = violacao.getPropertyPath().toString();

			if (!"ultimaAtualizacao".equals(nomePropriedade)) {

				parametros = new ArrayList<String>();
				parametros.add(nomePropriedade);
				adicionarParametrosAdicionais(parametros, violacao);

				if ("org.hibernate.validator.constraints.NotBlank"
						.equals(chaveMensagem)
						|| "javax.validation.constraints.NotNull"
								.equals(chaveMensagem)) {

					mensagensObrigatoriedade.add(new Mensagem(chaveMensagem,
							parametros));
				}

				mensagens.add(new Mensagem(chaveMensagem, parametros));
			}
		}

		if (mensagensObrigatoriedade.isEmpty()) {
			return mensagens;
		} else {
			return mensagensObrigatoriedade;
		}
	}

	private <E> void adicionarParametrosAdicionais(List<String> parametros,
			ConstraintViolation<E> violacao) {

		adicionarParametro(violacao, parametros, "value");
		adicionarParametro(violacao, parametros, "min");
		adicionarParametro(violacao, parametros, "max");
	}

	private <E> void adicionarParametro(ConstraintViolation<E> violacao,
			List<String> parametros, String atributo) {

		if (violacao.getConstraintDescriptor().getAttributes().get(atributo) != null) {
			parametros.add(violacao.getConstraintDescriptor().getAttributes()
					.get(atributo).toString());
		}
	}
}